#ifndef _FPDF_EMB_COMMON_H_
#define _FPDF_EMB_COMMON_H_

#include "fpdf_emb_annot.h"
#include "fpdf_emb_pencil.h"
#include "fpdf_emb_annot_ex.h"
#include "fpdf_emb_creator.h"
#include "fpdf_emb_docsaver.h"

extern "C" {
	extern void FX_OUTPUT_LOG_FUNC(const char*, ...);
	extern int FX_GET_TICK_FUNC();
};

#ifdef _FOXIT_DEBUG_
#define FOXIT_DEBUG1(msg) FX_OUTPUT_LOG_FUNC(msg)
#define FOXIT_DEBUG2(msg,para) FX_OUTPUT_LOG_FUNC(msg,para)
#define FOXIT_DEBUG3(msg,para1,para2) FX_OUTPUT_LOG_FUNC(msg,para1,para2)
#define FOXIT_DEBUG4(msg,para1,para2,para3) FX_OUTPUT_LOG_FUNC(msg,para1,para2,para3)
#define FOXIT_DEBUG5(msg,para1,para2,para3,param4) FX_OUTPUT_LOG_FUNC(msg,para1,para2,para3,param4)
#else
#define FOXIT_DEBUG1(msg)
#define FOXIT_DEBUG2(msg,para)
#define FOXIT_DEBUG3(msg,para1,para2)
#define FOXIT_DEBUG4(msg,para1,para2,para3)
#define FOXIT_DEBUG5(msg,para1,para2,para3,param4)
#endif

#ifdef _FOXIT_BENCHMARK_
static int g_Ticks[128], g_CallCount[128];

class _TickLogger
{
public:
	int m_Tick;
	FX_LPCSTR m_ID;
	_TickLogger(FX_LPCSTR id1) 
	{ 
		m_ID = id1; 
		FX_OUTPUT_LOG_FUNC("FPDFEMB TRACE: %s called", m_ID);
		m_Tick = FX_GET_TICK_FUNC(); 
	}
	~_TickLogger() 
	{
		int tick = FX_GET_TICK_FUNC() - m_Tick;
		FX_OUTPUT_LOG_FUNC("FPDFEMB BENCHMARK: %s, %d ticks", m_ID, tick);
	}
};

#define FOXIT_BENCHMARK(id1) _TickLogger tick(id1)
#else
#define FOXIT_BENCHMARK(id1)
#endif

extern jmp_buf* FPDFEMB_GetOOMJmpBuf();

class CEmb_Pause2 : public IFX_Pause, public CFX_Object
{
public:
	virtual FX_BOOL			NeedToPauseNow() {
		return m_pPause ? m_pPause->NeedPauseNow(m_pPause) : FALSE; 
	}
	FPDFEMB_PAUSE*			m_pPause;
};

class CEmb_FileRAccess : public IFX_FileRead, public CFX_Object
{
public:
	virtual CFX_ByteString	GetFullPath() { return CFX_ByteString(); }

	virtual FX_FILESIZE		GetSize()
	{ return (FX_FILESIZE)m_pFileAccess->GetSize(m_pFileAccess); }

	virtual FX_BOOL			ReadBlock(void* pBuf, FX_FILESIZE pos, size_t size)
	{ return m_pFileAccess->ReadBlock(m_pFileAccess, pBuf, (unsigned int)pos, (unsigned int)size) == FPDFERR_SUCCESS; }

	virtual void			Release() { delete this; }

	FPDFEMB_FILE_ACCESS*	m_pFileAccess;
};

class CEmb_FileWAccess : public IFX_FileWrite, public CFX_Object
{
public:	
	virtual FX_FILESIZE		GetSize()
	{ return (FX_FILESIZE)m_pFileAccess->GetSize(m_pFileAccess); }

	virtual FX_BOOL			Flush()
	{ return m_pFileAccess->Flush(m_pFileAccess) == FPDFERR_SUCCESS; }

	virtual	FX_BOOL			WriteBlock(const void* pData, FX_FILESIZE offset, size_t size)
	{ return m_pFileAccess->WriteBlock(m_pFileAccess, pData, (unsigned int)offset, (unsigned int)size) == FPDFERR_SUCCESS; }

	virtual void			Release() { delete this; }

	FPDFEMB_FILEWRITE_ACCESS*	m_pFileAccess;
};

class CEmb_FileRWRAccess : public IFX_FileRead, public CFX_Object
{
public:
	virtual CFX_ByteString	GetFullPath() { return CFX_ByteString(); }

	virtual FX_FILESIZE		GetSize()
	{ return (FX_FILESIZE)m_pFileAccess->GetSize(m_pFileAccess); }

	virtual FX_BOOL			ReadBlock(void* pBuf, FX_FILESIZE pos, size_t size)
	{ return m_pFileAccess->ReadBlock(m_pFileAccess, pBuf, (unsigned int)pos, (unsigned int)size) == FPDFERR_SUCCESS; }

	virtual void			Release() { delete this; }

	FPDFEMB_FILERW_ACCESS*	m_pFileAccess;
};

class CEmb_FileRWWAccess : public IFX_FileWrite, public CFX_Object
{
public:	
	virtual FX_FILESIZE		GetSize()
	{ return (FX_FILESIZE)m_pFileAccess->GetSize(m_pFileAccess); }

	virtual FX_BOOL			Flush()
	{ return m_pFileAccess->Flush(m_pFileAccess) == FPDFERR_SUCCESS; }

	virtual	FX_BOOL			WriteBlock(const void* pData, FX_FILESIZE offset, size_t size)
	{ return m_pFileAccess->WriteBlock(m_pFileAccess, pData, (unsigned int)offset, (unsigned int)size) == FPDFERR_SUCCESS; }

	virtual void			Release() { delete this; }

	FPDFEMB_FILERW_ACCESS*	m_pFileAccess;
};

class CEmb_MemFile : public IFX_FileRead, public CFX_Object
{
public:
	static IFX_FileRead*	CreateFileRead(unsigned char* data, int size) {
		if (data == NULL || size < 1) return NULL;
		CEmb_MemFile* pMemFile = FX_NEW CEmb_MemFile;
		pMemFile->m_pData = data;
		pMemFile->m_nSize = (size_t)size;
		return pMemFile;
	}

	virtual CFX_ByteString	GetFullPath() { return CFX_ByteString(); }
	virtual FX_FILESIZE		GetSize() { return (FX_FILESIZE)m_nSize; }

	virtual FX_BOOL			ReadBlock(void* pBuf, FX_FILESIZE pos, size_t size) { 
		if ((size_t)pos + size > m_nSize) return FALSE;
		FXSYS_memcpy(pBuf, m_pData + (size_t)pos, size);
		return TRUE;
	}

	virtual void			Release() { delete this; }

	unsigned char*			m_pData;
	size_t					m_nSize;
};


#endif // _FPDF_EMB_COMMON_H_